
array_class='''
cdef class UintArraySet(UintSet):
    cdef readonly u8 cur
    cdef inline u64 _cur(self): return self.cur
    cdef inline set_cur(self, u64 cur): self.cur = cur
    cdef UintSet init(self, u64 level):
        self.cur = 0
        return self
    
'''
array_class_uint='''
cdef class U{0}ArraySet(UintArraySet):
    cdef inline u64 _itemsize(self): return {1}'''

array_classn ='''
cdef class U{0}ArraySet{1}(U{0}ArraySet):
    cdef readonly u{0}[{1}] data
    cdef inline void* _data(self): return self.data
    cdef inline u64 _level(self): return {2}
'''

hash_class='''
cdef class UintHashSet(UintSet):
    cdef inline void* data
    cdef readonly u64 cur
    cdef readonly u8 level
    cdef inline u64 _cur(self): return self.cur
    cdef inline set_cur(self, u64 cur): self.cur = cur
    cdef inline void* _data(self): return self.data
    cdef inline u64 _level(self): return self.level
    cdef UintSet init(self, u64 level):
        self.cur = 0
        cdef u64 count = (1 << level), deleted_size=(count>>3)+1 if count&7 else count>>3
        self.data = py_calloc(self._itemsize()*count)
        return self
'''
hash_class_uint='''
cdef class U{0}HashSet(UintHashSet):
    cdef inline u64 _itemsize(self): return {1}'''

bitset_class='''
cdef class UintBitSet(UintSet):
    cdef u64* data
    cdef readonly u64 cur
    cdef u64 _level(self): 
        return (1<<self._itemsize())-8-log2(self._itemsize())
    cdef inline u64 _cur(self): return self.cur
    cdef inline set_cur(self, u64 cur): self.cur = cur
    cdef inline void* _data(self): return self.data
    cdef inline u64 _nbytes(self):
        (ONE<<(self._itemsize()<<3))>>3 # 2**(8*itemsize) /8
    cdef UintSet init(self, u64 level):
        self.cur = 0
        self.data = py_calloc(self._nbytes())
        return self
    '''

bitset_class_uint='''
cdef class U{0}BitSet(BitSet):
    cdef inline u64 _itemsize(self): return {1}'''

init_str='''
cdef init_u{0}_ARGS():
    cdef u64 i
    {1}
    for i in range(5, {2}):
        {3}
        '''

init_arrayset='''
    U{0}ARGS[{0}]=uintSetArgs({1}+8*i)'''

def log2(x):
    r=1
    x //= 2
    while x>0:
        r+=1
        x //=2
    return r


def code_gen(bitcount, firset_itemcount):
    s = f'''
#--------------------------------------------------u{bitcount} array set------------------------------------------------
cdef class U{bitcount}ArraySet(UintArraySet):
    cdef u64 _itemsize(self): return {bitcount} 
cdef class U{bitcount}HashSet(UintHashSet):
    cdef u64 _itemsize(self): return {bitcount}
'''
    itemsize = bitcount//8
    typename = f'u{bitcount}' if bitcount not in (24,40,48) else 'u8'
    max_hash_value = (bitcount)-3-log2(bitcount//8)
    names=[]
    for i in range(5):
        itemcount = firset_itemcount+8*i
        name=f'U{bitcount}ArraySet{itemcount}'
        names.append(name)
        s += f'''
cdef class {name}(UintArraySet):
    cdef readonly {typename}[{itemcount}] data    
    cdef void* _data(self): return self.data
'''
    s += f'''
cdef tuple u{bitcount}arraysets=({','.join(names)})
UINT_SET_CLASSES[{itemsize}]=u{bitcount}arraysets'''
    return s
def str_init(itemsize, first_itemcount):
    bitcount=itemsize*8
    max_hash_value = (bitcount)-3-log2(bitcount//8)
    s=f'init_UINT_SET_ARGS({itemsize}, {first_itemcount}, {max_hash_value})'
def dict_str(names, dict_name):
    kvs=[]
    for name in names:
        kv=f"<u64>(&{name}):'{name}'"
        value = name
        kvs.append(kv)
    return dict_name+'={' + ', '.join(kvs)+'}'

def code_func_name(first_itemcounts):
    nexts =['bitset64_next']
    searchs=['bitset64_in']
    inserts=['bitset64_insert']
    removes=['bitset64_remove']
    for i, first_itemcount in zip([2,3,4,5,6,8], first_itemcounts):
        bitcount = f'u{i * 8}'
        next_arr_name=f'next_{bitcount}_arrayset'
        next_hash_name = f'next_{bitcount}_hashset'
        search_arr_name = f'bisect_{bitcount}_in'
        insert_arr_name = f'bisect_insert_{bitcount}'
        remove_arr_name = f'bisect_remove_{bitcount}'
        search_hash_name = f'{bitcount}_hash_search_in'
        insert_hash_name = f'{bitcount}_hash_insert'
        remove_hash_name = f'{bitcount}_hash_remove'
        inserts += [insert_arr_name, insert_hash_name]
        nexts += [next_arr_name, next_hash_name]
        removes += [remove_arr_name, remove_hash_name]
        searchs += [search_arr_name, search_hash_name]
        bitcount = i * 8
        max_hash_value = (bitcount) - 3 - log2(bitcount // 8)
        init = f'init_UINT_SET_ARGS({i}, {first_itemcount}, {max_hash_value}, &{next_arr_name}, &{search_arr_name},&{insert_arr_name}, &{remove_arr_name}, &{next_hash_name}, &{search_hash_name}, &{insert_hash_name}, &{remove_hash_name})'
        print(init)
    n = dict_str(nexts,'nexts')
    i = dict_str(inserts,'inserts')
    r = dict_str(removes,'removes')
    s = dict_str(searchs,'searchs')
    print(n); print(i); print(r); print(s)


if __name__=='__main__':

    code_func_name([7,5,5,3,5,4])
    '''s=code_gen(16, 7)
    print(s)

    s=code_gen(32,5)
    print(s)

    s = code_gen(24, 5)
    print(s)

    s=code_gen(40, 3)
    print(s)

    s=code_gen(48, 5)
    print(s)

    s=code_gen(64, 4)
    print(s)'''